package com.ruoyi.cms.service.impl;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import com.ruoyi.cms.domain.*;
import com.ruoyi.cms.mapper.ArticleMapper;
import com.ruoyi.cms.mapper.TagsMapper;
import com.ruoyi.cms.service.IArticleService;
import com.ruoyi.cms.service.ICategoryService;
import com.ruoyi.cms.service.IMaterialUseService;
import com.ruoyi.cms.util.CmsConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.plugs.common.config.Global;
import com.ruoyi.plugs.common.utils.Guid;
import com.ruoyi.plugs.ehcache.util.EhCacheUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 文章管理Service业务层处理
 *
 * @author wujiyue
 * @date 2019-10-28
 */
@Service
public class ArticleServiceImpl implements IArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private TagsMapper tagsMapper;
    @Autowired
    private ICategoryService categoryService;
    @Autowired
    private IMaterialUseService materialUseService;

    private Cache<String, Category> categoryCache = CacheUtil.newLFUCache(100);
    private Cache<String, Tags> tagCache = CacheUtil.newLFUCache(100);

    /**
     * 查询文章管理
     *
     * @param id 文章管理ID
     * @return 文章管理
     */
    @Override
    public Article selectArticleById(String id) {
        Article article = articleMapper.selectArticleById(id);
        Map<String, Object> m = articleMapper.getArticleContent(id);
        if (m != null) {
            article.setContent(String.valueOf(m.get("content")));
            article.setContent_markdown_source(String.valueOf(m.get("content_markdown_source")));
        }
        selectCategory(article);
        selectTags(article);
        return article;
    }

    /**
     * 查询文章管理列表
     *
     * @param article 文章管理
     * @return 文章管理
     */
    @Override
    public List<Article> selectArticleList(Article article) {
        List<Article> articles = articleMapper.selectArticleList(article);
        selectTags(articles);
        selectCategory(articles);
        return articles;
    }

    /**
     * 新增文章管理
     *
     * @param article 文章管理
     * @return 结果
     */
    @Override
    @Transactional
    public int insertArticle(Article article) {
        article.setId(Guid.get());
        article.setCreateTime(DateUtils.getNowDate());
        article.setUpdateTime(DateUtils.getNowDate());
        SysUser user = ShiroUtils.getSysUser();
        article.setYhid(user.getUserId().toString());
        article.setDeleted(0);
        String tags = article.getTags();
        if (StringUtils.isNotEmpty(tags)) {
            if (!tags.endsWith(",")) {
                tags += ",";
                article.setTags(tags);
            }
        }
        article.setAvailable(CmsConstants.AUDIT_STATE_TODO);
        article.setAuthor(user.getUserName());
        article.setCreateBy(user.getUserId().toString());

        if (article.getCommentFlag() == null) {
            article.setCommentFlag("0");
        }
        if ("on".equals(article.getCommentFlag())) {
            article.setCommentFlag("1");
        }
        if ("off".equals(article.getCommentFlag())) {
            article.setCommentFlag("0");
        }
        int n = articleMapper.insertArticle(article);
        updateMaterialUse(article);
        n = articleMapper.insertArticleContent(article);
        return n;
    }

    private void updateMaterialUse(Article article) {
        materialUseService.deleteMaterialsUseByUse(CmsConstants.MATERIAL_USE_ARTICLE, article.getId(),
                CmsConstants.MATERIAL_USE_ARTICLE_COLUMN_NAME,
                CmsConstants.MATERIAL_USE_ARTICLE_MATERIAL_NAME);
        if (article.getCoverImageId() != null) {
            MaterialUse materialUse = new MaterialUse();
            materialUse.setMaterialId(article.getCoverImageId());
            materialUse.setUseTable(CmsConstants.MATERIAL_USE_ARTICLE);
            materialUse.setUseColumn(CmsConstants.MATERIAL_USE_ARTICLE_COLUMN_NAME);
            materialUse.setMaterialColumn(CmsConstants.MATERIAL_USE_ARTICLE_MATERIAL_NAME);
            materialUse.setType(MaterialUse.Type.NOT);
            materialUse.setUseId(article.getId());
            materialUseService.insertMaterialUse(materialUse);
        }
    }

    /**
     * 修改文章管理
     *
     * @param article 文章管理
     * @return 结果
     */
    @Override
    @Transactional
    public int updateArticle(Article article) {
        article.setUpdateTime(DateUtils.getNowDate());
        String tags = article.getTags();
        if (StringUtils.isNotEmpty(tags)) {
            if (!tags.endsWith(",")) {
                tags += ",";
                article.setTags(tags);
            }
        }
        SysUser user = ShiroUtils.getSysUser();
        article.setUpdateBy(user.getUserId().toString());
        article.setAvailable(CmsConstants.AUDIT_STATE_TODO);
        if (article.getCommentFlag() == null) {
            article.setCommentFlag("0");
        }
        if ("on".equals(article.getCommentFlag())) {
            article.setCommentFlag("1");
        }
        if ("off".equals(article.getCommentFlag())) {
            article.setCommentFlag("0");
        }
        int n = articleMapper.updateArticle(article);
        updateMaterialUse(article);
        n = articleMapper.updateArticleContent(article);
        return n;
    }

    /**
     * 删除文章管理对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteArticleByIds(String ids) {
        String[] idArray = Convert.toStrArray(ids);
        articleMapper.deleteArticleContentByIds(idArray);
        for (String id : idArray) {
            materialUseService.deleteMaterialsUseByUse(CmsConstants.MATERIAL_USE_ARTICLE, id,
                    CmsConstants.MATERIAL_USE_ARTICLE_COLUMN_NAME,
                    CmsConstants.MATERIAL_USE_ARTICLE_MATERIAL_NAME);
        }
        return articleMapper.deleteArticleByIds(idArray);
    }

    /**
     * 删除文章管理信息
     *
     * @param id 文章管理ID
     * @return 结果
     */
    @Override
    public int deleteArticleById(String id) {
        articleMapper.deleteArticleContentById(id);
        return articleMapper.deleteArticleById(id);
    }

    @Override
    public List<Article> selectArticlesByArticleRegionType(ArticleRegionType articleRegionType) {
        List<Article> list = null;
        if (Boolean.valueOf(Global.isCacheEnabled())) {
            list = (List<Article>) EhCacheUtils.getSysInfo("ArticleRegionType_", articleRegionType.getVal());
        }
        if (CollectionUtils.isEmpty(list)) {
            list = this.selectArticlesByArticleRegionTypeInDb(articleRegionType);
            if (Boolean.valueOf(Global.isCacheEnabled())) {
                EhCacheUtils.putSysInfo("ArticleRegionType_", articleRegionType.getVal(), list);
            }
        }
        //selectCategory(list);
        return list;
    }

    @Override
    public List<Article> selectArticlesRegionNotNull(Article article) {
        List<Article> list = articleMapper.selectArticlesRegionNotNull(article);
        selectCategory(list);
        return list;
    }

    @Override
    public List<Article> selectArticlesRegionIsNull(Article article) {
        List<Article> list = articleMapper.selectArticlesRegionIsNull(article);
        //selectCategory(list);
        return list;
    }

    @Override
    public int upVote(String id) {
        return articleMapper.upVote(id);
    }

    @Override
    public int articleLook(String id) {
        return articleMapper.articleLook(id);
    }

    @Override
    public void batchPublish(String[] ids) {
        articleMapper.batchPublish(ids);
    }

    @Override
    public List<Article> selectArticlesOfTimeline() {
        return articleMapper.selectArticlesOfTimeline();
    }

    @Override
    public int articleTagCount(String tagId) {
        return articleMapper.articleTagCount(tagId);
    }

    @Override
    public List<Map> sortInCategory(String categoryId) {
        return articleMapper.sortInCategory(categoryId);
    }


    private List<Article> selectArticlesByArticleRegionTypeInDb(ArticleRegionType articleRegionType) {
        Article queryForm = new Article();
        queryForm.setArticleRegion(articleRegionType.getVal());
        List<Article> list = this.selectArticleList(queryForm);
        selectCategory(list);
        return list;
    }

    private void selectCategory(List<Article> list) {
        list.forEach(a -> {
            String cid = a.getCategoryId();
            Category category = categoryCache.get(cid);
            if (category == null) {
                category = categoryService.selectCategoryById(Long.valueOf(cid));
                if (category != null) {
                    categoryCache.put(cid, category);
                }
            }
            if (category != null) {
                a.setCategory(category);
            }
        });
    }

    private void selectCategory(Article a) {

        String cid = a.getCategoryId();
        Category category = categoryCache.get(cid);
        if (category == null) {
            category = categoryService.selectCategoryById(Long.valueOf(cid));
            if (category != null) {
                categoryCache.put(cid, category);
            }
        }
        if (category != null) {
            a.setCategory(category);
        }
    }

    private void selectTags(List<Article> articles) {

        //转换标签名称，这部分可以使用缓存提升性能
        articles.forEach(a -> {
            String tagsStr = a.getTags();
            if (StringUtils.isNotEmpty(tagsStr)) {
                String[] tagsArr = Convert.toStrArray(tagsStr);
                String tags_name = "";
                List<Tags> tags = Lists.newArrayList();
                for (String id : tagsArr) {
                    if (StringUtils.isNotEmpty(id)) {

                        Tags tag = tagCache.get(id);
                        if (tag == null) {
                            tag = tagsMapper.selectTagsById(Long.valueOf(id));
                            tagCache.put(id, tag);
                        }
                        tags.add(tag);
                        if (tag != null) {
                            tags_name += tag.getTagName() + ",";
                        }
                    }
                }
                if (tags_name.endsWith(",")) {
                    tags_name = StringUtils.substring(tags_name, 0, tags_name.length() - 1);
                }
                a.setTags_name(tags_name);
                a.setTagList(tags);
            }
        });


    }

    private void selectTags(Article a) {
        String tids = a.getTags();//tagIds
        if (StringUtils.isEmpty(tids)) {
            return;
        }
        String[] arr = Convert.toStrArray(tids);
        List<Tags> tags = Lists.newArrayList();
        for (String tid : arr) {
            if (StringUtils.isEmpty(tid)) {
                continue;
            }
            Tags tag = tagCache.get(tid);
            if (tag == null) {
                tag = tagsMapper.selectTagsById(Long.valueOf(tid));
                tagCache.put(tid, tag);
            }
            tags.add(tag);
        }
        a.setTagList(tags);
    }

    @Override
    public AjaxResult saveSort(Map map) {
        try {
            String sort = String.valueOf(map.get("sort"));
            if (!"".equals(sort)) {
                String[] sx = sort.split(",");
                for (int i = 0; i < sx.length; i++) {
                    String[] arr = sx[i].split("_");
                    Integer id = Integer.valueOf(arr[1]);
                    articleMapper.updateSort(id, arr[2]);
                }
            }
            return AjaxResult.success("排序成功！");
        } catch (Exception e) {
            return AjaxResult.error("排序失败！");
        }
    }

}
